package com.logica.mdm.webservices.messages;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;

import com.logica.mdm.webservices.dao.beans.AddressResultBean;
import com.logica.mdm.webservices.dao.beans.PartyContractResultBean;
import com.logica.mdm.webservices.dao.beans.PartyElectronicAddressResultBean;
import com.logica.mdm.webservices.dao.beans.PartyResultBean;
import com.logica.mdm.webservices.dao.beans.XrefResultBean;
import com.logica.mdm.webservices.messages.beans.AddressBean;
import com.logica.mdm.webservices.messages.beans.AddressListBean;
import com.logica.mdm.webservices.messages.beans.As400IdListBean;
import com.logica.mdm.webservices.messages.beans.ContractBean;
import com.logica.mdm.webservices.messages.beans.CrmIdListBean;
import com.logica.mdm.webservices.messages.beans.ElectronicAddressBean;
import com.logica.mdm.webservices.messages.beans.ElectronicAddressListBean;
import com.logica.mdm.webservices.messages.beans.NexibookIdListBean;
import com.logica.mdm.webservices.messages.beans.PartyBean;
import com.logica.mdm.webservices.messages.beans.PartyWithAddressAndContractBean;
import com.logica.mdm.webservices.util.MdmStringUtils;
import com.logica.mdm.webservices.util.RequestWithParamsBean;

/**
 * Utility class to search MDM.
 */
public class SearchPartyUtils {
	
	/**
	 * Create a query with params from the search parameter.
	 * @param searchParams the search parameter
	 * @return the corresponding query with params
	 */
	public static RequestWithParamsBean buildRequest(SearchPartyRequest searchParams) {
		RequestWithParamsBean result = null;
		
		String searchLocation = searchParams.getSearchLocation();
		
		// SearchLocation has already been validate so we know that it works
		if (SearchPartyConstants.NEXIBOOK_SRC.equals(searchLocation)) {
			result = buildNexibookRequest(searchParams);
		} else if (SearchPartyConstants.SIGEO_SRC.equals(searchLocation)) {
			result = buildSigeoRequest(searchParams);
		} else if (SearchPartyConstants.HERMES_SRC.equals(searchLocation)) {
			result = buildHermesRequest(searchParams);
		} else if (SearchPartyConstants.CTI_SRC.equals(searchLocation)) {
			result = buildCTIRequest(searchParams);
		} else {
			throw new UnsupportedOperationException("The SearchLocation must be known");
		}
		
		return result;
	}
	
	/**
	 * Build a SQL request xith filter criteria
	 * @param partyFilterCriteria filter criteria concerning the Party
	 * @param otherFilterCriteria filter criteria not concerning the Party
	 * @param recordsToReturn number of record to return
	 * @return a sql String
	 */
	private static String buildSQLRequest(List<String> partyFilterCriteria, List<String> otherFilterCriteria, Integer recordsToReturn) {
		StringBuilder sb = new StringBuilder(4700);
		if (recordsToReturn != null) {
			sb.append(SearchPartyConstants.PARTY_START_PAGINATE);
		}
		sb.append(SearchPartyConstants.PARTY_SELECT_QUERY);
		if (partyFilterCriteria.isEmpty()) {
			sb.append(SearchPartyConstants.PARTY_C_PARTY_FROM);
		} else {
			sb.append(SearchPartyConstants.PARTY_INNER_QUERY_1);
			sb.append(StringUtils.join(partyFilterCriteria.toArray(), " AND "));
			sb.append(SearchPartyConstants.PARTY_INNER_QUERY_2);
		}
		sb.append(SearchPartyConstants.PARTY_JOIN_QUERY);
		if (!otherFilterCriteria.isEmpty()) {
			sb.append(" WHERE ");
			sb.append(StringUtils.join(otherFilterCriteria.toArray(), " AND "));
		}
		sb.append(SearchPartyConstants.PARTY_FINAL_FROM_NAME);
		sb.append(SearchPartyConstants.PARTY_ORDER_BY);
		
		if (recordsToReturn != null) {
			sb.append(SearchPartyConstants.PARTY_END_PAGINATE);
		}
		
		return sb.toString();
	}

	/**
	 * Create a query with params from the search parameter for a Nexibook request.
	 * @param searchParams the search parameter
	 * @return the corresponding query with params
	 */
	private static RequestWithParamsBean buildNexibookRequest(SearchPartyRequest searchParams) {
		List<String> partyFilterCriteria = new ArrayList<String>();
		List<String> otherFilterCriteria = new ArrayList<String>();
		Map<String, Object> filterParams = new HashMap<String, Object>();
		
		if (!StringUtils.isEmpty(searchParams.getLastName())) {
			partyFilterCriteria.add(MdmStringUtils.getLowerWithoutAccentQuery("c_party.last_name")
					+ " LIKE :lastName");
			filterParams.put("lastName", MdmStringUtils.toLowerWithoutAccent(searchParams.getLastName()) + "%");
		}
		if (!StringUtils.isEmpty(searchParams.getFirstName())) {
			partyFilterCriteria.add(MdmStringUtils.getLowerWithoutAccentQuery("c_party.first_name")
					+ " LIKE :firstName");
			filterParams.put("firstName", MdmStringUtils.toLowerWithoutAccent(searchParams.getFirstName()) + "%");
		}
		if (!StringUtils.isEmpty(searchParams.getPostalCode())) {
			otherFilterCriteria.add("mv_pkg_ws_party_address_pp.postal_cd LIKE :postalCd");
			filterParams.put("postalCd", searchParams.getPostalCode() + "%");
		}
		if (!StringUtils.isEmpty(searchParams.getCountryCode())) {
			otherFilterCriteria.add("LOWER(TRIM(mv_pkg_ws_party_address_pp.country_code)) = :countryCode");
			filterParams.put("countryCode", searchParams.getCountryCode().trim().toLowerCase());
		}
		if (!StringUtils.isEmpty(searchParams.getCrmId())) {
			otherFilterCriteria.add("LOWER(mv_pkg_ws_party_crm_id.pkey_src_object) = :crmId");
			filterParams.put("crmId", searchParams.getCrmId().toLowerCase());
		}
		if (!StringUtils.isEmpty(searchParams.getMdmId())) {
			partyFilterCriteria.add("c_party.rowid_object = RPAD(:rowidObject, 14, ' ')");
			filterParams.put("rowidObject", searchParams.getMdmId().trim());
		}
		if (searchParams.getRecordsToReturn() != null) {
			filterParams.put("maxResult", searchParams.getRecordsToReturn());
		}

		// Create the request
		RequestWithParamsBean request = new RequestWithParamsBean();
		
		request.setSqlQuery(buildSQLRequest(partyFilterCriteria, otherFilterCriteria, searchParams.getRecordsToReturn()));
		request.setParams(filterParams);

		return request;
	}

	/**
	 * Create a query with paramsfrom the search parameter for a Sigeo request.
	 * @param searchParams the search parameter
	 * @return the corresponding query with params
	 */
	private static RequestWithParamsBean buildSigeoRequest(SearchPartyRequest searchParams) {
		List<String> partyFilterCriteria = new ArrayList<String>();
		List<String> otherFilterCriteria = new ArrayList<String>();
		Map<String, Object> filterParams = new HashMap<String, Object>();
		
		if (!StringUtils.isEmpty(searchParams.getPartyType())) {
			partyFilterCriteria.add("LOWER(TRIM(c_party.party_type)) = :partyType");
			filterParams.put("partyType", searchParams.getPartyType().trim().toLowerCase());
		}
		if (!StringUtils.isEmpty(searchParams.getGender())) {
			partyFilterCriteria.add("LOWER(TRIM(c_party.gender_cd)) = :genderCd");
			filterParams.put("genderCd", searchParams.getGender().trim().toLowerCase());
		}
		if (!StringUtils.isEmpty(searchParams.getLegalForm())) {
			partyFilterCriteria.add("LOWER(TRIM(c_party.legal_form_cd)) = :legalFormCd");
			filterParams.put("legalFormCd", searchParams.getLegalForm().trim().toLowerCase());
		}
		
		if (!StringUtils.isEmpty(searchParams.getLastName())) {
			partyFilterCriteria.add(MdmStringUtils.getLowerWithoutAccentQuery("c_party.last_name") + " LIKE :lastName");
			filterParams.put("lastName", MdmStringUtils.toLowerWithoutAccent(searchParams.getLastName()) + "%");
		}
		if (!StringUtils.isEmpty(searchParams.getFirstName())) {
			partyFilterCriteria.add(MdmStringUtils.getLowerWithoutAccentQuery("c_party.first_name") + " LIKE :firstName");
			filterParams.put("firstName", MdmStringUtils.toLowerWithoutAccent(searchParams.getFirstName()) + "%");
		}
		if (!StringUtils.isEmpty(searchParams.getStreetName())) {
			otherFilterCriteria.add(MdmStringUtils.getLowerWithoutAccentQuery("mv_pkg_ws_party_address_pp.street_name") + " = :streetName");
			filterParams.put("streetName", MdmStringUtils.toLowerWithoutAccent(searchParams.getStreetName()));
		}
		if (!StringUtils.isEmpty(searchParams.getPostalCode())) {
			otherFilterCriteria.add("mv_pkg_ws_party_address_pp.postal_cd = :postalCd");
			filterParams.put("postalCd", searchParams.getPostalCode());
		}
		if (!StringUtils.isEmpty(searchParams.getCityName())) {
			otherFilterCriteria.add(MdmStringUtils.getLowerWithoutAccentQuery("mv_pkg_ws_party_address_pp.city_name") + " LIKE :cityName");
			filterParams.put("cityName", MdmStringUtils.toLowerWithoutAccent(searchParams.getCityName()) + "%");
		}
		if (!StringUtils.isEmpty(searchParams.getPhoneNumber())) {
			otherFilterCriteria.add("(TRIM(mv_pkg_ws_party_phone.dom) = :homePhone OR TRIM(mv_pkg_ws_party_phone.por) = :cellPhone OR TRIM(mv_pkg_ws_party_phone.bur) = :workPhone OR TRIM(mv_pkg_ws_party_phone.fax) = :faxPhone)");
			// we add four time the phone number because we search among the four phone numbers
			filterParams.put("homePhone", searchParams.getPhoneNumber().trim());
			filterParams.put("cellPhone", searchParams.getPhoneNumber().trim());
			filterParams.put("workPhone", searchParams.getPhoneNumber().trim());
			filterParams.put("faxPhone", searchParams.getPhoneNumber().trim());
		}
		if (!StringUtils.isEmpty(searchParams.getRefClient())) {
			partyFilterCriteria.add("LOWER(TRIM(c_party.debranchement_sigeo)) = :refClient");
			filterParams.put("refClient", searchParams.getRefClient().toLowerCase());
		}
		if (searchParams.getRecordsToReturn() != null) {
			filterParams.put("maxResult", searchParams.getRecordsToReturn());
		}

		
		// Create the request
		RequestWithParamsBean request = new RequestWithParamsBean();
		
		request.setSqlQuery(buildSQLRequest(partyFilterCriteria, otherFilterCriteria, searchParams.getRecordsToReturn()));
		request.setParams(filterParams);

		return request;
	}
	
	/**
	 * Create a query with params from the search parameter for a Hermes request.
	 * @param searchParams the search parameter
	 * @return the corresponding query with params
	 */
	private static RequestWithParamsBean buildHermesRequest(SearchPartyRequest searchParams) {
		List<String> partyFilterCriteria = new ArrayList<String>();
		List<String> otherFilterCriteria = new ArrayList<String>();
		Map<String, Object> filterParams = new HashMap<String, Object>();
		
		if (!StringUtils.isEmpty(searchParams.getLastName())) {
			partyFilterCriteria.add(MdmStringUtils.getLowerWithoutAccentQuery("c_party.last_name") + " LIKE :lastName");
			filterParams.put("lastName", MdmStringUtils.toLowerWithoutAccent(searchParams.getLastName()) + "%");
		}
		if (!StringUtils.isEmpty(searchParams.getFirstName())) {
			partyFilterCriteria.add(MdmStringUtils.getLowerWithoutAccentQuery("c_party.first_name") + " LIKE :firstName");
			filterParams.put("firstName", MdmStringUtils.toLowerWithoutAccent(searchParams.getFirstName())+ "%");
		}

		if (!StringUtils.isEmpty(searchParams.getGender())) {
			partyFilterCriteria.add("LOWER(TRIM(c_party.gender_cd)) = :genderCd");
			filterParams.put("genderCd", searchParams.getGender().trim().toLowerCase());
		}
		if (!StringUtils.isEmpty(searchParams.getStreetName())) {
			otherFilterCriteria.add("mv_pkg_ws_party_address_pp.street_name LIKE :streetName");
			filterParams.put("streetName", searchParams.getStreetName() + "%");
		}
		if (!StringUtils.isEmpty(searchParams.getPostalCode())) {
			otherFilterCriteria.add("mv_pkg_ws_party_address_pp.postal_cd LIKE :postalCd");
			filterParams.put("postalCd", searchParams.getPostalCode() + "%");
		}
		if (!StringUtils.isEmpty(searchParams.getCityName())) {
			otherFilterCriteria.add(MdmStringUtils.getLowerWithoutAccentQuery("mv_pkg_ws_party_address_pp.city_name") + " = :cityName");
			filterParams.put("cityName", MdmStringUtils.toLowerWithoutAccent(searchParams.getCityName()));
		}
		if (!StringUtils.isEmpty(searchParams.getCountryCode())) {
			otherFilterCriteria.add("LOWER(TRIM(mv_pkg_ws_party_address_pp.country_code)) = :countryCode");
			filterParams.put("countryCode", searchParams.getCountryCode().trim().toLowerCase());
		}
		if (!StringUtils.isEmpty(searchParams.getPhoneNumber())) {
			otherFilterCriteria.add("(TRIM(mv_pkg_ws_party_phone.dom) = :homePhone OR TRIM(mv_pkg_ws_party_phone.por) = :cellPhone OR TRIM(mv_pkg_ws_party_phone.bur) = :workPhone OR TRIM(mv_pkg_ws_party_phone.fax) = :faxPhone)");
			// we add four time the phone number because we search among the four phone numbers
			filterParams.put("homePhone", searchParams.getPhoneNumber().trim());
			filterParams.put("cellPhone", searchParams.getPhoneNumber().trim());
			filterParams.put("workPhone", searchParams.getPhoneNumber().trim());
			filterParams.put("faxPhone", searchParams.getPhoneNumber().trim());
		}
		if (!StringUtils.isEmpty(searchParams.getContractNumber())) {
			otherFilterCriteria.add("TRIM(c_contract.numero_contrat) = :numeroContrat");
			filterParams.put("numeroContrat", searchParams.getContractNumber().trim());
		}
		if (!StringUtils.isEmpty(searchParams.getContractOffice())) {
			otherFilterCriteria.add(MdmStringUtils.getLowerWithoutAccentQuery("c_contract.contract_office") + " = :contractOffice");
			filterParams.put("contractOffice", MdmStringUtils.toLowerWithoutAccent(searchParams.getContractOffice()));
		}
		if (!StringUtils.isEmpty(searchParams.getElectronicAddress())) {
			otherFilterCriteria.add("LOWER(TRIM(pkg_ws_party_e_address_pp.electronic_address)) LIKE :electronicAddress");
			filterParams.put("electronicAddress", searchParams.getElectronicAddress().trim().toLowerCase() + "%");
		}
		if (!StringUtils.isEmpty(searchParams.getRefClient())) {
			partyFilterCriteria.add("LOWER(TRIM(c_party.debranchement_sigeo)) = :refClient");
			filterParams.put("refClient", searchParams.getRefClient().toLowerCase());
		}
		if (!StringUtils.isEmpty(searchParams.getCrmId())) {
			otherFilterCriteria.add("LOWER(mv_pkg_ws_party_crm_id.pkey_src_object) = :crmId");
			filterParams.put("crmId", searchParams.getCrmId().toLowerCase());
		}
		if (searchParams.getRecordsToReturn() != null) {
			filterParams.put("maxResult", searchParams.getRecordsToReturn());
		}

		// Create the request
		RequestWithParamsBean request = new RequestWithParamsBean();
		
		request.setSqlQuery(buildSQLRequest(partyFilterCriteria, otherFilterCriteria, searchParams.getRecordsToReturn()));
		request.setParams(filterParams);
		
		return request;
	}
	
	/**
	 * Create a query with params from the search parameter for a CTI request.
	 * @param searchParams the search parameter
	 * @return the corresponding query with params
	 */
	private static RequestWithParamsBean buildCTIRequest(SearchPartyRequest searchParams) {
		return buildNexibookRequest(searchParams);
	}
	
	/**
	 * Validate the input request.
	 * The request need a search Location. Each location has a different validation rule.
	 * @param searchParams the search parameter
	 * @return <null> if the request is valid, a string with an error message if not
	 */
	public static String validateRequest(SearchPartyRequest searchParams) {
		// The result String
		String result = null;
		
		String searchLocation = searchParams.getSearchLocation();
		
		if (StringUtils.isEmpty(searchLocation)) {
			result = "Invalid input: you must specify a search location";
		} else {
			if (SearchPartyConstants.NEXIBOOK_SRC.equals(searchLocation)) {
				result = validateNexibookRequest(searchParams);
			} else if (SearchPartyConstants.SIGEO_SRC.equals(searchLocation)) {
				result = validateSigeoRequest(searchParams);
			} else if (SearchPartyConstants.HERMES_SRC.equals(searchLocation)) {
				result = validateHermesRequest(searchParams);
			} else if (SearchPartyConstants.CTI_SRC.equals(searchLocation)) {
				result = validateCTIRequest(searchParams);
			} else {
				result = "Invalid input: invalid search location";
			}
		}
		
		return result;
	}
	
	/**
	 * Validate the input request when requesting from nexibook.
	 * @param searchParams the search parameter
	 * @return <null> if the request is valid, a string with an error message if not
	 */
	private static String validateNexibookRequest(SearchPartyRequest searchParams) {
		// The result String
		String result = null;
		
		if (StringUtils.isEmpty(searchParams.getLastName())
				&& StringUtils.isEmpty(searchParams.getFirstName())
				&& StringUtils.isEmpty(searchParams.getPhoneNumber())
				&& StringUtils.isEmpty(searchParams.getPostalCode())
				&& StringUtils.isEmpty(searchParams.getCountryCode())
				&& StringUtils.isEmpty(searchParams.getMdmId())
				&& StringUtils.isEmpty(searchParams.getCrmId())) {
			result = "Invalid input: you must specify at least one of these fields [LastName - FirstName - PhoneNumber - PostalCode - CountryCode - MDM Id - CRM Id]";
		}
		
		return result;
	}
	
	/**
	 * Validate the input request when requesting from Sigeo.
	 * @param searchParams the search parameter
	 * @return <null> if the request is valid, a string with an error message if not
	 */
	private static String validateSigeoRequest(SearchPartyRequest searchParams) {
		// The result String
		String result = null;
		
		if (StringUtils.isEmpty(searchParams.getPartyType())
				&& StringUtils.isEmpty(searchParams.getGender())
				&& StringUtils.isEmpty(searchParams.getLegalForm())
				&& StringUtils.isEmpty(searchParams.getLastName())
				&& StringUtils.isEmpty(searchParams.getFirstName())
				&& StringUtils.isEmpty(searchParams.getStreetName())
				&& StringUtils.isEmpty(searchParams.getPostalCode())
				&& StringUtils.isEmpty(searchParams.getCityName())
				&& StringUtils.isEmpty(searchParams.getPhoneNumber())
				&& StringUtils.isEmpty(searchParams.getRefClient())
				&& StringUtils.isEmpty(searchParams.getMdmId())) {
			result = "Invalid input: you must specify at least one of these fields [PartyType - Gender - LegalForm - LastName - FirstName - StreetName - PostalCode - CityName - PhoneNumber - RefClient - MDM Id ]";
		}
		
		return result;
	}
	
	/**
	 * Validate the input request when requesting from Hermes.
	 * @param searchParams the search parameter
	 * @return <null> if the request is valid, a string with an error message if not
	 */
	private static String validateHermesRequest(SearchPartyRequest searchParams) {
		// The result String
		String result = null;
		
		if (StringUtils.isEmpty(searchParams.getGender())
				&& StringUtils.isEmpty(searchParams.getLastName())
				&& StringUtils.isEmpty(searchParams.getFirstName())
				&& StringUtils.isEmpty(searchParams.getStreetName())
				&& StringUtils.isEmpty(searchParams.getPostalCode())
				&& StringUtils.isEmpty(searchParams.getCityName())
				&& StringUtils.isEmpty(searchParams.getCountryCode())
				&& StringUtils.isEmpty(searchParams.getPhoneNumber())
				&& StringUtils.isEmpty(searchParams.getContractNumber())
				&& StringUtils.isEmpty(searchParams.getContractOffice())
				&& StringUtils.isEmpty(searchParams.getElectronicAddress())
				&& StringUtils.isEmpty(searchParams.getRefClient())
				&& StringUtils.isEmpty(searchParams.getMdmId())
				&& StringUtils.isEmpty(searchParams.getCrmId())) {
			result = "Invalid input: you must specify at least one of these fields [Gender - LastName - FirstName - StreetName - PostalCode - CityName - CountryCode - PhoneNumber - ContractNumber - ContractOffice - ElectronicAddress - RefClient - CRM Id - MDM Id]";
		}
		
		return result;
	}
	
	/**
	 * Validate the input request when requesting from CTI.
	 * @param searchParams the search parameter
	 * @return <null> if the request is valid, a string with an error message if not
	 */
	private static String validateCTIRequest(SearchPartyRequest searchParams) {
		return validateNexibookRequest(searchParams);
	}
	
	/**
	 * Utility method to convert result PartyResultBean list to a list of Party beans.
	 * @param inputList the PartyResultBean List to convert
	 * @param searchLocation the searchLocation (useful to convert the results)
	 * @return the converted list
	 */
	public static List<PartyBean> convertRecord(List<PartyResultBean> inputList, String searchLocation) {
		List<PartyBean> result = new ArrayList<PartyBean>();
		
		if (inputList != null) {
			for (PartyResultBean record : inputList) {
				PartyBean party = mdmPartyToPartyBean(record, searchLocation);
				result.add(party);
			}
		}
		return result;
	}

	/**
	 * Convert a list of result from the Database to a list of result corresponding to the search location
	 * @param partyIn the result from the database
	 * @param searchlocation the searchLocation
	 * @return the corresponding result
	 */
	public static List<PartyWithAddressAndContractBean> mdmPartyListToPartyListBean(
			List<PartyResultBean> partiesIn, String searchlocation) {
		List<PartyWithAddressAndContractBean> result = new ArrayList<PartyWithAddressAndContractBean>();
		
		for (PartyResultBean partyIn : partiesIn) {
			PartyBean party = mdmPartyToPartyBean(partyIn, searchlocation);
			if(party != null){
				result.add(SearchPartyUtils.partyBeanToPartyWithAddressAndContractBean(party));
			}
		}
		
		return result;
	}
	
	/**
	 * Convert a PartyBean to a PartyWithAddressAndContractBean.
	 * @param party the partyBean
	 * @return the corresponding result
	 */
	private static PartyWithAddressAndContractBean partyBeanToPartyWithAddressAndContractBean(
			PartyBean party) {
		PartyWithAddressAndContractBean result = new PartyWithAddressAndContractBean();
		
		if(party.getMdmId()!= null){
			result.setMdmId(party.getMdmId());
		}
		if(party.getLastName()!= null){
			result.setLastName(party.getLastName());
		}
		if(party.getFirstName()!= null){
			result.setFirstName(party.getFirstName());
		}
		if(party.getNamePrefix()!= null){
			result.setNamePrefix(party.getNamePrefix());
		}
		if(party.getGender()!= null){
			result.setGender(party.getGender());
		}
		if(party.getHomePhoneNumber()!= null){
			result.setHomePhoneNumber(party.getHomePhoneNumber());
		}
		if(party.getCellPhoneNumber()!= null){
			result.setCellPhoneNumber(party.getCellPhoneNumber());
		}
		if(party.getWorkPhoneNumber()!= null){
			result.setWorkPhoneNumber(party.getWorkPhoneNumber());
		}
		if(party.getFaxPhoneNumber()!= null){
			result.setFaxPhoneNumber(party.getFaxPhoneNumber());
		}
		if(party.getFlagPartenaire()!= null){
			result.setFlagPartenaire(party.getFlagPartenaire());
		}
		if(party.getFlagVip()!= null){
			result.setFlagVip(party.getFlagVip());
		}
		if(party.getLegalForm()!= null){
			result.setLegalForm(party.getLegalForm());
		}
		if(party.getPartyType()!= null){
			result.setPartyType(party.getPartyType());
		}
		if(party.getRefClient()!= null){
			result.setRefClient(party.getRefClient());
		}
		if(party.getSigeoId()!= null){
			result.setSigeoId(party.getSigeoId());
		}
		
		return result;
	}

	/**
	 * Convert a result from the Database to a result corresponding to the search location
	 * @param partyIn the result from the database
	 * @param searchlocation the searchLocation
	 * @return the corresponding result
	 */
	private static PartyBean mdmPartyToPartyBean(PartyResultBean partyIn, String searchlocation) {
		PartyBean result = null;
		
		if (SearchPartyConstants.NEXIBOOK_SRC.equals(searchlocation)) {
			result = mdmPartyToNexibookPartyBean(partyIn);
		} else if (SearchPartyConstants.SIGEO_SRC.equals(searchlocation)) {
			result = mdmPartyToSigeoPartyBean(partyIn);
		} else if (SearchPartyConstants.HERMES_SRC.equals(searchlocation)) {
			result = mdmPartyToHermesPartyBean(partyIn);
		} else if (SearchPartyConstants.CTI_SRC.equals(searchlocation)) {
			result = mdmPartyToCTIPartyBean(partyIn);
		} else {
			throw new UnsupportedOperationException("The SearchLocation must be known");
		}
		
		return result;
	}
	
	/**
	 * Convert a Database Party to a partyBean with informations for Nexibook
	 * @param partyIn the Database Party
	 * @return a partyBean with informations for Nexibook
	 */
	private static PartyBean mdmPartyToNexibookPartyBean(PartyResultBean partyIn) {
		PartyBean result = null;
		if (partyIn != null) {
			result = new PartyBean();
			if (!StringUtils.isEmpty(partyIn.getNamePrefixCd())) {
				result.setNamePrefix(partyIn.getNamePrefixCd());
			}
			if (!StringUtils.isEmpty(partyIn.getLastName())) {
				result.setLastName(partyIn.getLastName());
			}
			if (!StringUtils.isEmpty(partyIn.getFirstName())) {
				result.setFirstName(partyIn.getFirstName());
			}
			else
			{
				result.setFirstName("INCONNU");
			}
			if (partyIn.getUnitNumber() != null
					|| partyIn.getFloorNumber() != null) {
				String addressLine1 = (partyIn.getUnitNumber() != null) ? partyIn.getUnitNumber().toString() : null;
				if (addressLine1 != null) {
					addressLine1.concat(" ");
				}
				addressLine1.concat((partyIn.getFloorNumber() != null) ? partyIn.getFloorNumber().toString() : "");
				result.setAddressLine1(addressLine1);
			}
			if (!StringUtils.isEmpty(partyIn.getStreetNumber())
					|| !StringUtils.isEmpty(partyIn.getStreetType())
					|| !StringUtils.isEmpty(partyIn.getStreetName())) {
				String[] components = new String[]{partyIn.getStreetNumber(),
						partyIn.getStreetType(), partyIn.getStreetName()};
				String addressLine2 = StringUtils.join(components, " ");
				addressLine2 = addressLine2.trim();
				result.setAddressLine2(addressLine2);
			}
			if (!StringUtils.isEmpty(partyIn.getAddressLine5())) {
				result.setLocality(partyIn.getAddressLine5());
			}
			if (!StringUtils.isEmpty(partyIn.getPostalCd())) {
				result.setPostalCode(partyIn.getPostalCd());
			}
			if (!StringUtils.isEmpty(partyIn.getCityName())) {
				result.setCityName(partyIn.getCityName());
			}
			if (!StringUtils.isEmpty(partyIn.getCountryName())) {
				result.setCountryName(partyIn.getCountryName());
			}
			if (!StringUtils.isEmpty(partyIn.getCountryCode())) {
				result.setCountryCode(partyIn.getCountryCode());
			}
			if (!StringUtils.isEmpty(partyIn.getHexacleVoie())) {
				result.setHexacleVoie(partyIn.getHexacleVoie());
			}
			if (!StringUtils.isEmpty(partyIn.getHexacleLocalite())) {
				result.setHexacleLocalite(partyIn.getHexacleLocalite());
			}
			if (!StringUtils.isEmpty(partyIn.getHomePhoneNumber())) {
				result.setHomePhoneNumber(partyIn.getHomePhoneNumber());
			}
			if (!StringUtils.isEmpty(partyIn.getCellPhoneNumber())) {
				result.setCellPhoneNumber(partyIn.getCellPhoneNumber());
			}
			if (!StringUtils.isEmpty(partyIn.getWorkPhoneNumber())) {
				result.setWorkPhoneNumber(partyIn.getWorkPhoneNumber());
			}
//			if (!StringUtils.isEmpty(partyIn.getElectronicAddress())) {
//				result.setElectronicAddress(partyIn.getElectronicAddress());
//			}
			if (!StringUtils.isEmpty(partyIn.getFlagPartenaire())) {
				result.setFlagPartenaire(partyIn.getFlagPartenaire());
			}
			if (!StringUtils.isEmpty(partyIn.getRowidObject())) {
				result.setMdmId(partyIn.getRowidObject());
			}
//			if (!StringUtils.isEmpty(partyIn.getCrmId())) {
//				result.setCrmId(partyIn.getCrmId());
//			}
//			if (!StringUtils.isEmpty(partyIn.getLogementId())) {
//				result.setAs400Id(partyIn.getLogementId());
//				//FIXME differencier Nexibook et AS400
//				result.setNexibookId(partyIn.getLogementId());
//			}
		}
		return result;
	}
	
	/**
	 * Convert a Database Party to a partyBean with informations for Sigeo
	 * @param partyIn the Database party
	 * @return a partyBean with informations for Sigeo
	 */
	private static PartyBean mdmPartyToSigeoPartyBean(PartyResultBean partyIn) {
		PartyBean result = null;
		if (partyIn != null) {
			result = new PartyBean();
			if (!StringUtils.isEmpty(partyIn.getPartyTypeDisp())) {
				result.setPartyType(partyIn.getPartyTypeDisp());
			}
			if (!StringUtils.isEmpty(partyIn.getGenderDisp())) {
				result.setGender(partyIn.getGenderDisp());
			}
			if (!StringUtils.isEmpty(partyIn.getLibelleLegalForm())) {
				result.setLegalForm(partyIn.getLibelleLegalForm());
			}
			if (!StringUtils.isEmpty(partyIn.getNamePrefixCd())) {
				result.setNamePrefix(partyIn.getNamePrefixCd());
			}
			if (!StringUtils.isEmpty(partyIn.getLastName())) {
				result.setLastName(partyIn.getLastName());
			}
			if (!StringUtils.isEmpty(partyIn.getFirstName())) {
				result.setFirstName(partyIn.getFirstName());
			}
			if (!StringUtils.isEmpty(partyIn.getStreetNumber())) {
				result.setStreetNumber(partyIn.getStreetNumber());
			}
			if (!StringUtils.isEmpty(partyIn.getStreetType())
					|| !StringUtils.isEmpty(partyIn.getStreetName())) {
				String[] components = new String[]{partyIn.getStreetType(), partyIn.getStreetName()};
				String streetTypeAndName = StringUtils.join(components, " ");
				streetTypeAndName = streetTypeAndName.trim();
				result.setStreetTypeAndName(streetTypeAndName);
			}
			if (!StringUtils.isEmpty(partyIn.getAddressLine5())) {
				result.setLocality(partyIn.getAddressLine5());
			}
			if (!StringUtils.isEmpty(partyIn.getPostalCd())) {
				result.setPostalCode(partyIn.getPostalCd());
			}
			if (!StringUtils.isEmpty(partyIn.getCityName())) {
				result.setCityName(partyIn.getCityName());
			}
			if (!StringUtils.isEmpty(partyIn.getCountryName())) {
				result.setCountryName(partyIn.getCountryName());
			}
			if (!StringUtils.isEmpty(partyIn.getHexacleVoie())) {
				result.setHexacleVoie(partyIn.getHexacleVoie());
			}
			if (!StringUtils.isEmpty(partyIn.getHexacleLocalite())) {
				result.setHexacleLocalite(partyIn.getHexacleLocalite());
			}
			if (!StringUtils.isEmpty(partyIn.getHomePhoneNumber())) {
				result.setHomePhoneNumber(partyIn.getHomePhoneNumber());
			}
			if (!StringUtils.isEmpty(partyIn.getCellPhoneNumber())) {
				result.setCellPhoneNumber(partyIn.getCellPhoneNumber());
			}
			if (!StringUtils.isEmpty(partyIn.getWorkPhoneNumber())) {
				result.setWorkPhoneNumber(partyIn.getWorkPhoneNumber());
			}
			if (!StringUtils.isEmpty(partyIn.getFaxPhoneNumber())) {
				result.setFaxPhoneNumber(partyIn.getFaxPhoneNumber());
			}
//			if (!StringUtils.isEmpty(partyIn.getElectronicAddress())) {
//				result.setElectronicAddress(partyIn.getElectronicAddress());
//			}
//			if (!StringUtils.isEmpty(partyIn.getNumeroContrat())) {
//				result.setContractNumber(partyIn.getNumeroContrat());
//			}
//			if (!StringUtils.isEmpty(partyIn.getContractOffice())) {
//				result.setContractOffice(partyIn.getContractOffice());
//			}
			if (!StringUtils.isEmpty(partyIn.getDebranchementSigeo())) {
				result.setRefClient(partyIn.getDebranchementSigeo());
				result.setSigeoId(MdmStringUtils.filterAlphaSigeoID(partyIn.getDebranchementSigeo()));
			}
			if (!StringUtils.isEmpty(partyIn.getRowidObject())) {
				result.setMdmId(partyIn.getRowidObject());
			}
//			if (!StringUtils.isEmpty(partyIn.getCrmId())) {
//				result.setCrmId(partyIn.getCrmId());
//			}
//			if (!StringUtils.isEmpty(partyIn.getLogementId())) {
//				result.setAs400Id(partyIn.getLogementId());
//				//FIXME differencier Nexibook et AS400
//				result.setNexibookId(partyIn.getLogementId());
//			}
		}
		return result;
	}
	
	/**
	 * Convert a Database Party to a partyBean with informations for Hermes
	 * @param partyIn the Database Party
	 * @return a partyBean with informations for Hermes
	 */
	private static PartyBean mdmPartyToHermesPartyBean(PartyResultBean partyIn) {
		// Same output as for Sigeo
		return mdmPartyToSigeoPartyBean(partyIn);
	}
	
	/**
	 * Convert a Database Party to a partyBean with informations for CTI
	 * @param partyIn the Database Party
	 * @return a partyBean with informations for CTI
	 */
	private static PartyBean mdmPartyToCTIPartyBean(PartyResultBean partyIn) {
		// Start with the same output as for Nexibook
		PartyBean result = mdmPartyToNexibookPartyBean(partyIn);
		
		if (result != null) {
			if (!StringUtils.isEmpty(partyIn.getFlagVip())) {
				result.setFlagVip(partyIn.getFlagVip());
			}
			if (!StringUtils.isEmpty(partyIn.getTypeContrat())) {
				result.setContractType(partyIn.getTypeContrat());
			}
			if (!StringUtils.isEmpty(partyIn.getStatutContrat())) {
				result.setContractStatus(partyIn.getStatutContrat());
			}
			if (!StringUtils.isEmpty(partyIn.getDateDebutValiditeContrat())) {
				result.setContractValidityStartDate(partyIn.getDateDebutValiditeContrat());
			}
			if (!StringUtils.isEmpty(partyIn.getDateFinValiditeContrat())) {
				result.setContractValidityEndDate(partyIn.getDateFinValiditeContrat());
			}
		}
		
		return result;
	}

	public static ElectronicAddressListBean convertPartyElectronicAddressListRecord(
			List<PartyElectronicAddressResultBean> inputList) {
		ElectronicAddressListBean result = null;
		List<ElectronicAddressBean> electronicAddressList = null;
		
		if (inputList != null && !inputList.isEmpty()) {
			result = new ElectronicAddressListBean();
			electronicAddressList = new ArrayList<ElectronicAddressBean>();
			
			for (PartyElectronicAddressResultBean record : inputList) {
				ElectronicAddressBean address = mdmAddressElectronicToAddressElectronicBean(record);
				electronicAddressList.add(address);
			}
			result.setElectronicAddress(electronicAddressList);
		}
		return result;
	}

	public static ElectronicAddressBean mdmAddressElectronicToAddressElectronicBean(
			PartyElectronicAddressResultBean record) {
		ElectronicAddressBean result = null;
		
		if(record != null){
			result = new ElectronicAddressBean();
			result.setAddress(record.getElectronicAddress());
			result.setType(record.getElectronicAddressType());
		}
		
		return result;
	}
	
	/**
	 * Utility method to convert result AddressResultbean list to a list of Address beans.
	 * @param inputList the AddressResultbean List to convert
	 * @return the converted list
	 */
	public static AddressListBean convertAddressRecord(List<AddressResultBean> inputList) {
		AddressListBean result = null;
		List<AddressBean> addressList = null;
		
		if (inputList != null && !inputList.isEmpty()) {
			result = new AddressListBean();
			addressList = new ArrayList<AddressBean>();
			
			for (AddressResultBean record : inputList) {
				AddressBean address = mdmAddressToAddressBean(record);
				addressList.add(address);
			}
			result.setAddress(addressList);
		}
		return result;
	}
	
	/**
	 * Convert a Datatbase Address to an address Bean
	 * @param addressIn the database Address
	 * @return the corresponding AddressBean 
	 */
	public static AddressBean mdmAddressToAddressBean(AddressResultBean addressIn) {
		AddressBean result = null;
		if (addressIn != null) {
			result = new AddressBean();
			
			if (!StringUtils.isEmpty(addressIn.getAddressType())) {
				result.setAddressTypeCode(addressIn.getAddressType());
			}
			if (!StringUtils.isEmpty(addressIn.getAddressTypeDesc())) {
				result.setAddressType(addressIn.getAddressTypeDesc());
			}
			if (!StringUtils.isEmpty(addressIn.getStreetNumber())) {
				result.setStreetNumber(addressIn.getStreetNumber());
			}
			if (!StringUtils.isEmpty(addressIn.getStreetType())
					|| !StringUtils.isEmpty(addressIn.getStreetName())) {
				String[] components = new String[]{addressIn.getStreetType(), addressIn.getStreetName()};
				String streetTypeAndName = StringUtils.join(components, " ");
				streetTypeAndName = streetTypeAndName.trim();
				result.setStreetTypeAndName(streetTypeAndName);
			}
			if (!StringUtils.isEmpty(addressIn.getAddressLine2())) {
				result.setAddressLine2(addressIn.getAddressLine2());
			}
			if (!StringUtils.isEmpty(addressIn.getAddressLine3())) {
				result.setAddressLine3(addressIn.getAddressLine3());
			}
			if (!StringUtils.isEmpty(addressIn.getMailBoxNumber())) {
				result.setMailBoxNumber(addressIn.getMailBoxNumber());
			}
			if (!StringUtils.isEmpty(addressIn.getAddressLine5())) {
				result.setLocality(addressIn.getAddressLine5());
			}
			if (!StringUtils.isEmpty(addressIn.getPostalCd())) {
				result.setPostalCode(addressIn.getPostalCd());
			}
			if (!StringUtils.isEmpty(addressIn.getCityName())) {
				result.setCityName(addressIn.getCityName());
			}
			if (!StringUtils.isEmpty(addressIn.getCountryName())) {
				result.setCountryName(addressIn.getCountryName());
			}
			if (!StringUtils.isEmpty(addressIn.getHexacleVoie())) {
				result.setHexacleVoie(addressIn.getHexacleVoie());
			}
			if (!StringUtils.isEmpty(addressIn.getHexacleLocalite())) {
				result.setHexacleLocalite(addressIn.getHexacleLocalite());
			}
		}
		return result;
	}
	
	/**
	 * Utility method to convert result XrefResultBean list to a list of source keys.
	 * @param inputList the XrefResultBean List to convert
	 * @return the converted list
	 */
	public static CrmIdListBean convertListCrmIdXrefRecord(List<XrefResultBean> inputList) {
		CrmIdListBean result = null;
		List<String> crmIdList = null;
		
		if (inputList != null && !inputList.isEmpty()) {
			result = new CrmIdListBean();
			crmIdList = new ArrayList<String>();
			
			for (XrefResultBean record : inputList) {
				crmIdList.add(record.getPkeySrcObject());
			}
			result.setCrmId(crmIdList);
		}
		return result;
	}	
	
	/**
	 * Utility method to convert result XrefResultBean list to a list of source keys.
	 * @param inputList the XrefResultBean List to convert
	 * @return the converted list
	 */
	public static NexibookIdListBean convertNexibookIdXrefRecord(List<XrefResultBean> inputList) {
		NexibookIdListBean result = null;
		List<String> nexibookIdList = null;
		
		if (inputList != null && !inputList.isEmpty()) {
			result = new NexibookIdListBean();
			nexibookIdList = new ArrayList<String>();
			
			for (XrefResultBean record : inputList) {
				nexibookIdList.add(record.getPkeySrcObject());
			}
			result.setNexibookId(nexibookIdList);
		}
		return result;
	}	
	
	/**
	 * Utility method to convert result XrefResultBean list to a list of source keys.
	 * @param inputList the XrefResultBean List to convert
	 * @return the converted list
	 */
	public static As400IdListBean convertAs400IdXrefRecord(List<XrefResultBean> inputList) {
		As400IdListBean result = null;
		List<String> As400IdList = null;
		
		if (inputList != null && !inputList.isEmpty()) {
			result = new As400IdListBean();
			As400IdList = new ArrayList<String>();
			
			for (XrefResultBean record : inputList) {
				As400IdList.add(record.getPkeySrcObject());
			}
			result.setAs400Id(As400IdList);
		}
		return result;
	}

	public static ContractBean convertContractRecord(
			PartyContractResultBean record) {
		ContractBean result = null;
		
		if(record != null){
			result = new ContractBean();
			result.setContractNumber(record.getContractNumber());
			result.setContractOffice(record.getContractOffice());
		}
		
		return result;
	}
	
}
